﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;

namespace Td.Additional.Log
{
    /// <summary>
    /// Class to combine different log classes.
    /// </summary>
    public class CombinedLog : List<ILog>, ILog
    {
        #region Properties

        /// <summary>
        /// Gets or sets the log level.
        /// </summary>
        /// <value>The log level.</value>
        public LogLevel LogLevel
        {
            get
            {
                LogLevel result = Count == 1 ? this[0].LogLevel : LogLevel.None;
                foreach (ILog log in this)
                    if (log.LogLevel > result)
                        result = log.LogLevel;
                return result;
            }
            set
            {
                foreach (ILog log in this)
                    log.LogLevel = value;
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether [log full qualified method name].
        /// </summary>
        /// <value>
        /// 	<c>true</c> if [log full qualified method name]; otherwise, <c>false</c>.
        /// </value>
        public bool LogFullQualifiedMethodName
        {
            get
            {
                Boolean result = true;
                foreach (ILog log in this)
                    if (log.LogFullQualifiedMethodName != result)
                        return false;
                return result;
            }
            set
            {
                foreach (ILog log in this)
                    log.LogFullQualifiedMethodName = value;
            }
        }

        #endregion

        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="CombinedLog"/> class.
        /// </summary>
        public CombinedLog() : base() { }

        /// <summary>
        /// Initializes a new instance of the <see cref="CombinedLog"/> class.
        /// </summary>
        /// <param name="log">The log.</param>
        public CombinedLog(ILog log)
            : this()
        {
            Add(log);
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="CombinedLog"/> class.
        /// </summary>
        /// <param name="logs">The logs.</param>
        public CombinedLog(params ILog[] logs)
            : base(logs)
        {
        }

        #endregion

        #region ILog members

        /// <summary>
        /// New debug message.
        /// </summary>
        /// <param name="message">The message.</param>
        public void Debug(String message)
        {
            foreach (ILog log in this)
                log.Debug(message);
        }

        /// <summary>
        /// New debug message.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="args">The arguments.</param>
        public void Debug(String message, params object[] args)
        {
            foreach (ILog log in this)
                log.Debug(message, args);
        }

        /// <summary>
        /// New information message.
        /// </summary>
        /// <param name="message">The message.</param>
        public void Info(String message)
        {
            foreach (ILog log in this)
                log.Info(message);
        }

        /// <summary>
        /// New information message.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="args">The arguments.</param>
        public void Info(String message, params object[] args)
        {
            foreach (ILog log in this)
                log.Info(message, args);
        }

        /// <summary>
        /// New warning message.
        /// </summary>
        /// <param name="message">The message.</param>
        public void Warn(String message)
        {
            foreach (ILog log in this)
                log.Warn(message);
        }

        /// <summary>
        /// New warning message.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="args">The arguments.</param>
        public void Warn(String message, params object[] args)
        {
            foreach (ILog log in this)
                log.Warn(message, args);
        }

        /// <summary>
        /// New error message.
        /// </summary>
        /// <param name="message">The message.</param>
        public void Error(String message)
        {
            foreach (ILog log in this)
                log.Error(message);
        }

        /// <summary>
        /// New error message.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="args">The arguments.</param>
        public void Error(String message, params object[] args)
        {
            foreach (ILog log in this)
                log.Error(message, args);
        }

        /// <summary>
        /// New critical message.
        /// </summary>
        /// <param name="message">The message.</param>
        public void Critical(String message)
        {
            foreach (ILog log in this)
                log.Critical(message);
        }

        /// <summary>
        /// New critical message.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="args">The arguments.</param>
        public void Critical(String message, params object[] args)
        {
            foreach (ILog log in this)
                log.Critical(message, args);
        }

        /// <summary>
        /// New fatal message.
        /// </summary>
        /// <param name="message">The message.</param>
        public void Fatal(String message)
        {
            foreach (ILog log in this)
                log.Fatal(message);
        }

        /// <summary>
        /// New fatal message.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="args">The arguments.</param>
        public void Fatal(String message, params object[] args)
        {
            foreach (ILog log in this)
                log.Fatal(message, args);
        }

        #endregion

        #region Replaced methods

        /// <summary>
        /// Add an object to the end of <see cref="T:System.Collections.Generic.List`1"/>.
        /// </summary>
        /// <param name="item">The object that should be added at the end of <see cref="T:System.Collections.Generic.List`1"/>. The value could be null for reference types.</param>
        public new void Add(ILog item)
        {
            if (item == this)
                throw new ArgumentException("Circular reference when adding a combined log to itself", "item");
            base.Add(item);
        }

        #endregion
    }
}